//
//  IWVideoRecordingController.swift
//  VideoRecording
//
//  Created by goWhere on 16/7/4.
//  Copyright © 2016年 iwhere. All rights reserved.
//

import UIKit
import AVFoundation
import Photos

@objc protocol IWVideoRecordingDelegate {
    func recordCompleted(_ viewController:IWVideoRecordingController,videoPath:String)
    func recordCancel(_ viewController:IWVideoRecordingController)
}

class IWVideoRecordingController: UIViewController {
  
    private let recordContentView:UIView = UIView()
    private let operationContentView:UIView = UIView()
    private let btnBack:CXPowerButton = CXPowerButton(type: .image)
    private var ringProgressView:CXRingProgressView = CXRingProgressView()
    private let btnRecord:UIButton = UIButton(type: .custom)
    private let btnDeleteRecord:CXPowerButton = CXPowerButton(type: .image)
    private let btnConfirmRecord:CXPowerButton = CXPowerButton(type: .image)
  
    //  最常视频录制时间，单位 秒
    let MaxVideoRecordTime = 20
    
    //  MARK: - Properties
    //  视频捕获会话，他是 input 和 output 之间的桥梁，它协调着 input 和 output 之间的数据传输
    let captureSession = AVCaptureSession()
    //  视频输入设备，前后摄像头
    var camera: AVCaptureDevice?
    //  展示界面
    var previewLayer: AVCaptureVideoPreviewLayer!
    //  HeaderView 
    var headerView: UIView!
    
    //  音频输入设备
    let audioDevice = AVCaptureDevice.default(for: AVMediaType.audio)
    //  将捕获到的视频输出到文件
    let fileOut = AVCaptureMovieFileOutput()
  
    //  录制时间Timer
    var timer: Timer?
    var secondCount = 0
    
    //  表示当时是否在录像中
    var isRecording = false
    weak var delegate:IWVideoRecordingDelegate?
    
    override func loadView() {
        super.loadView()
      
    }
    //  MARK: - LifeCycle
    override func viewDidLoad() {
        super.viewDidLoad()
      
        self.view.addSubview(self.recordContentView)
        self.recordContentView.frame = self.view.bounds
        self.view.addSubview(self.operationContentView)
        self.operationContentView.frame = self.view.bounds
        self.operationContentView.backgroundColor = UIColor.clear
        //  录制视频基本设置
        setupAVFoundationSettings()
        //  UI 布局
        setupButton()
        setupOperationView()

    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.isNavigationBarHidden = true
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.isNavigationBarHidden = false
    }
    
    //  MARK: - Private Methods
    /// 对视频进行基本设置
    private func setupAVFoundationSettings() {
      
        // 相机
        camera = cameraWithPosition(position: AVCaptureDevice.Position.back)
        //  设置视频清晰度
        captureSession.sessionPreset = AVCaptureSession.Preset.vga640x480
        //  添加视频、音频输入设备
        if let videoInput = try? AVCaptureDeviceInput(device: camera!) {
            captureSession.addInput(videoInput)
        }
        if audioDevice != nil,
           let audioInput = try? AVCaptureDeviceInput(device: audioDevice!) {
            captureSession.addInput(audioInput)
        }
        //  添加视频捕获输出
        self.captureSession.addOutput(fileOut)
        //  使用 AVCaptureVideoPreviewLayer 可以将摄像头拍到的实时画面显示在 ViewController 上
        let videoLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
        videoLayer.frame = view.bounds
        videoLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.recordContentView.layer.addSublayer(videoLayer)
        previewLayer = videoLayer
        //  启动 Session 回话
        self.captureSession.startRunning()
  }
    
    /// 选择摄像头
    private func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
        let tempDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: position)
        for item in tempDevices.devices {
            if item.position == position {
                return item
            }
        }
        return nil
    }
    
    
    //  MARK: - UI Settings
    /**
     创建按钮
     */
    private func setupButton() {
      
    }
    
    //  headerView
    private func setupOperationView() {
        self.btnBack.addTarget(self, action: #selector(backAction), for: .touchUpInside)
        self.btnBack.setIcon("\u{e705}", for: .normal)
        // TODO:>
//        self.btnBack.iconLabel.cxFont = FontAsset.Icon.size(30)
        self.btnBack.iconLabel.cxFont = FontAsset.PingFangSC_Regular.size(15)
        self.btnBack.iconLabel.openShadow = true
        self.btnBack.setIconColor(UIColor(hexStr: "#FFFFFF", alpha: 1.0), for: .normal)
        self.operationContentView.addSubview(self.btnBack)
        self.btnBack.snp.makeConstraints { (make) in
            make.centerY.equalTo(self.operationContentView.snp.top).offset(vSafeTop + 22)
            make.leading.equalToSuperview().offset(15)
            make.width.height.equalTo(44)
        }

        self.ringProgressView.marginLeft = 5
        self.ringProgressView.marginTop = 5
        self.ringProgressView.ringWidth = 3.0
        self.ringProgressView.backgroundColor = UIColor(hexStr: "#FFFFFF", alpha: 0.4)
        self.ringProgressView.ringColor = UIColor(hexStr: "#333333", alpha: 1.0)
        self.ringProgressView.progressColor = UIColor(hexStr: "#FFFFFF", alpha: 1.0)
        self.ringProgressView.progress = 0
        self.ringProgressView.layer.masksToBounds = true
        self.ringProgressView.layer.cornerRadius = 30
        self.operationContentView.addSubview(self.ringProgressView)
        self.ringProgressView.snp.makeConstraints { (make) in
          make.centerX.equalToSuperview()
          make.bottom.equalToSuperview().offset(-vSafeBottom - 40)
          make.width.height.equalTo(60)
        }
      
        self.btnRecord.addTarget(self, action: #selector(onClickedRecordButton(_:)), for: .touchUpInside)
        self.btnRecord.backgroundColor = UIColor(hexStr: "#FFFFFF", alpha: 0.65)
        self.btnRecord.layer.masksToBounds = true
        self.btnRecord.layer.cornerRadius = (60 - 8 * 2) * 0.5
        self.btnRecord.setTitle("开始", for: .normal)
        self.btnRecord.setTitleColor(UIColor(hexStr: "#333333", alpha: 1.0), for: .normal)
        self.btnRecord.titleLabel?.font = FontAsset.PingFangSC_Regular.size(14.0)
        self.ringProgressView.addSubview(self.btnRecord)
        self.btnRecord.snp.makeConstraints { (make) in
            make.edges.equalTo(UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8))
        }
        
        self.btnDeleteRecord.isHidden = true
        self.btnDeleteRecord.setIcon("\u{e721}", for: .normal)
        self.btnDeleteRecord.iconLabel.openShadow = true
        // TODO:>
        self.btnDeleteRecord.iconLabel.cxFont = FontAsset.PingFangSC_Regular.size(15)
//        self.btnDeleteRecord.iconLabel.cxFont = FontAsset.Icon.size(30)
        self.btnDeleteRecord.setIconColor(UIColor(hexStr: "#FFFFFF", alpha: 1.0), for: .normal)
        self.operationContentView.addSubview(self.btnDeleteRecord)
        self.btnDeleteRecord.snp.makeConstraints { (make) in
            make.centerY.equalTo(self.ringProgressView)
            make.trailing.equalTo(self.ringProgressView.snp.leading).offset(-15)
            make.width.height.equalTo(44)
        }

        self.btnConfirmRecord.isHidden = true
        self.btnConfirmRecord.setIcon("\u{e716}", for: .normal)
        self.btnConfirmRecord.iconLabel.openShadow = true
        // TODO:>
        self.btnConfirmRecord.iconLabel.cxFont = FontAsset.PingFangSC_Regular.size(15)
//        self.btnConfirmRecord.iconLabel.cxFont = FontAsset.Icon.size(30)
        self.btnConfirmRecord.setIconColor(UIColor(hexStr: "#FFFFFF", alpha: 1.0), for: .normal)
        self.operationContentView.addSubview(self.btnConfirmRecord)
        self.btnConfirmRecord.snp.makeConstraints { (make) in
            make.centerY.equalTo(self.ringProgressView)
            make.leading.equalTo(self.ringProgressView.snp.trailing).offset(15)
            make.width.height.equalTo(44)
        }
    }
    
    //  MARK: - UIButton Actions
    //  按钮点击事件
    @objc private func onClickedRecordButton(_ sender:UIButton){
        if !self.isRecording {
            self.startRecord()
        }else {
            self.stopRecord()
        }
    }
    private func startRecord(){
      //  开启计时器
      timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(videoRecordingTotolTime), userInfo: nil, repeats: true)
        if !isRecording {
            //  记录状态： 录像中 ...
            isRecording = true
            captureSession.startRunning()
            //  设置录像保存地址，在 Documents 目录下，名为 当前时间.mp4
            let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
            let documentDirectory = path[0] as String
            let filePath: String? = "\(documentDirectory)/\(Date()).mp4"
            let fileUrl: URL? = URL(fileURLWithPath: filePath!)
            //  启动视频编码输出
            fileOut.startRecording(to: fileUrl!, recordingDelegate: self)
        }
    }
    private func stopRecord(){
        //  关闭计时器
        timer?.invalidate()
        timer = nil
        secondCount = 0
        if isRecording {
            //  停止视频编码输出
            captureSession.stopRunning()
            //  记录状态： 录像结束 ...
            isRecording = false
//            //  开始结束按钮颜色改变
            self.ringProgressView.progress = 1.0
        }
      
    }
    //  录制时间
    @objc private func videoRecordingTotolTime() {
        secondCount += 1
        
        //  判断是否录制超时
        if secondCount / 10 == MaxVideoRecordTime {
            timer?.invalidate()
            self.stopRecord()
            return
        }
        if secondCount == 0 {
          self.ringProgressView.progress = 0
          self.btnRecord.setTitle("开始", for: .normal)
        }else {
          self.ringProgressView.progress = Float(secondCount) / Float(MaxVideoRecordTime * 10)
          let recordTile = String(format: "%.1fs", Float(secondCount)/10)
          self.btnRecord.setTitle(recordTile, for: .normal)
      }
    }
    
    //  返回上一页
    @objc private func backAction() {
      self.delegate?.recordCancel(self)
    }
    
    //  调整摄像头
    @objc private func changeCamera(cameraSideButton: UIButton) {
        cameraSideButton.isSelected = !cameraSideButton.isSelected
        captureSession.stopRunning()
        //  首先移除所有的 input
        if let  allInputs = captureSession.inputs as? [AVCaptureDeviceInput] {
            for input in allInputs {
                captureSession.removeInput(input)

            }
        }
        
        changeCameraAnimate()
        
        //  添加音频输出
        if audioDevice != nil,
            let audioInput = try? AVCaptureDeviceInput(device: audioDevice!) {
            self.captureSession.addInput(audioInput)
        }

        if cameraSideButton.isSelected {
            camera = cameraWithPosition(position: .front)
            if let input = try? AVCaptureDeviceInput(device: camera!) {
                captureSession.addInput(input)
            }
            
//            if flashLightButton.isSelected {
//                flashLightButton.isSelected = false
//            }
        } else {
            camera = cameraWithPosition(position: .back)
            if let input = try? AVCaptureDeviceInput(device: camera!) {
                captureSession.addInput(input)
            }
        }
    }
    
    //  切换动画
    private func changeCameraAnimate() {
        let changeAnimate = CATransition()
        changeAnimate.delegate = self
        changeAnimate.duration = 0.4
        changeAnimate.type = CATransitionType(rawValue: "oglFlip")
        changeAnimate.subtype = CATransitionSubtype.fromRight
        previewLayer.add(changeAnimate, forKey: "changeAnimate")
    }
    
    //  开启闪光灯
    @objc private func switchFlashLight(flashButton: UIButton) {
        if self.camera?.position == AVCaptureDevice.Position.front {
            return
        }
        let camera = cameraWithPosition(position: .back)
        if camera?.torchMode == AVCaptureDevice.TorchMode.off {
            do {
                try camera?.lockForConfiguration()
            } catch let error as NSError {
                print("开启闪光灯失败 ： \(error)")
            }
            
            camera?.torchMode = AVCaptureDevice.TorchMode.on
            camera?.flashMode = AVCaptureDevice.FlashMode.on
            camera?.unlockForConfiguration()
            
            flashButton.isSelected = true
        } else {
            do {
                try camera?.lockForConfiguration()
            } catch let error as NSError {
                print("关闭闪光灯失败： \(error)")
            }
            
            camera?.torchMode = AVCaptureDevice.TorchMode.off
            camera?.flashMode = AVCaptureDevice.FlashMode.off
            camera?.unlockForConfiguration()
            
            flashButton.isSelected = false
        }
    }
    
    override var shouldAutorotate: Bool {
        return false
    }
    
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .portrait
    }
}

// MARK: - CAAnimationDelegate
extension IWVideoRecordingController: CAAnimationDelegate {
    /// 动画开始
    func animationDidStart(_ anim: CAAnimation) {
        captureSession.startRunning()
    }
    
    /// 动画结束
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    }
}

// MARK: - AVCaptureFileOutputRecordingDelegate
extension IWVideoRecordingController: AVCaptureFileOutputRecordingDelegate {
    /// 开始录制
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        
    }
    
    /// 结束录制
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
      let tempDelegate = self.delegate
      let tempVC = self
      let tempOutputFileURL = outputFileURL
      self.dismiss(animated: true) {
        tempDelegate?.recordCompleted(tempVC, videoPath: tempOutputFileURL.absoluteString)
      }
    }
}

